# -*- coding: utf-8 -*-


from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5
from Crypto import Hash

import base64
import json
import collections

import functools

import logging
_logger = logging.getLogger(__name__)

try:
    def import_key(key_type):
        with open( key_type + '-key.pem','rb')as x:
            key = x.read()
        return key
    
    AES_KEY = import_key('aes')
    AES_KEY = bytes.decode(AES_KEY).strip()

    RSA_KEY = import_key('rsa')
    RSA_KEY_obj = RSA.importKey(RSA_KEY)
    RSA_KEY = RSA_KEY_obj.publickey().exportKey()
    
except:
    _logger.warning('Could not Load key file!')


def sort_for_value(value):
    if isinstance(value, dict):
        return sort_by_key(value)
    elif isinstance(value, (list,tuple)):
        return [ sort_for_value(item) for item in value]
    else:
        return value


def sort_by_key(obj):
    dic = collections.OrderedDict()
    keys = list(obj.keys())
    keys.sort()
    for key in keys:
        dic[key] = sort_for_value(obj[key])

    return dic


def verify(data):
    body2 = data.copy()
    # timestamp = body2.get('timestamp')
    signature = body2.get('signature')

    body2['signature'] = '_signature_'
    body3 = sort_by_key(body2)
    body4 = json.dumps(body3, separators=(',', ':'))

    signature = base64.b64decode(signature)
    verifier = sign_PKCS1_v1_5.new(RSA.importKey(RSA_KEY))
    _rand_hash = Hash.SHA256.new()
    _rand_hash.update(body4.encode())
    verify = verifier.verify(_rand_hash, signature)
    return verify #true / false


def aes_decrypt(data):
    key = AES_KEY
    unpad = lambda s : s[0:-s[-1]]
    cipher = AES.new(key)
    result2 = base64.b64decode(data)
    decrypted = unpad(cipher.decrypt(result2))
    return  decrypted


"""
1 AES 解密, 得到 参数数据 + 时间戳 + 签名
11 BASE64 解密
12 取 aes-key
13 AES 解密 
2 验证签名正确
21 将签名替换为签名模版
22 排序
23 转JSON
24 读取 rsa-key
25 签名 BASE64 解密
26 SHA256 验签
3 将 参数数据 做 BASE64 解码, 得到 JSON 串
4 JSON 串 转 Dict
"""
def decrypt(data):
    data = aes_decrypt(data)
    data = data.decode()
    data = json.loads(data)

    vv = verify(data)
    if vv:
        data2 = data['data']
        data3 = base64.b64decode(data2).decode()
        data4 = json.loads(data3)
        return data4
    else:
        return None


"""
对外接口函数

"""
def decode(func):
    # 装饰器函数, 接收一个参数, 解密后, 生成加密前的参数列表
    @functools.wraps(func)
    def wrapper( *args, **kwargs):
        data = kwargs.get('data')
        data = decrypt(data)
        return func(*args, **data)
    return wrapper


"""
密钥生成工具:
aes-key.pem 的内容为 32位长度的任意字符串
rsa-key.pem 的内容为 rsa加密算法的 私钥
两个密钥文件 前端与服务端一致

部署:
需要两个密钥文件
aes-key.pem
rsa-key.pem
放置路径:
部署时放置在 /opt/odoo 目录下
"""


if __name__ == "__main__":
    with open('data.txt','r') as fp:
        res = fp.read()

    print(111)
    print(res)
    print(222 )
    
    res = decrypt(res)
    print(res)
    pass


